package at.codejedi.sto.gui.combat;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Calendar;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpringLayout;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

import at.codejedi.sto.config.Configuration;
import at.codejedi.sto.model.combat.Entry;
import at.codejedi.sto.model.combat.IBattleStatistic;

public class EntryView extends JPanel {

	private class EntryTableModel extends AbstractTableModel {

		private static final long serialVersionUID = 8125397096375182624L;

		private final String[] columnNames = {
				Configuration.getLabel("Entry.Time"),
				Configuration.getLabel("Entry.FromType"),
				Configuration.getLabel("Entry.SkillName"),
				Configuration.getLabel("Entry.SkillReference"),
				Configuration.getLabel("Entry.ToName"),
				Configuration.getLabel("Entry.ToType"),
				Configuration.getLabel("Entry.DamageSourceName"),
				Configuration.getLabel("Entry.DamageType"),
				Configuration.getLabel("Entry.Modifier"),
				Configuration.getLabel("Entry.NetDamage"),
				Configuration.getLabel("Entry.RawDamage")

		};

		private List<Entry> entries;

		public EntryTableModel(List<Entry> entries) {
			this.entries = entries;
		}

		@Override
		public int getColumnCount() {
			return columnNames.length;
		}

		@Override
		public String getColumnName(int col) {
			return columnNames[col];
		}

		public String[] getColumnNames() {
			return columnNames;
		}

		@Override
		public int getRowCount() {
			return entries.size();
		}

		@Override
		public Object getValueAt(int row, int col) {
			Entry entry = entries.get(row);

			switch (col) {
			case (0):
				Calendar calendar = entry.getTime();
				return Configuration.getDateTimeFormat().format(
						calendar.getTime());
			case (1):
				return entry.getFromType();
			case (2):
				return entry.getSkillName();
			case (3):
				return entry.getSkillReference();
			case (4):
				return entry.getToName();
			case (5):
				return entry.getToType();
			case (6):
				return entry.getDamageSourceName();
			case (7):
				return entry.getDamageType();
			case (8):
				return entry.getModifier();
			case (9):
				return entry.getNetDamage();
			case (10):
				return entry.getRawDamage();
			}

			throw new IndexOutOfBoundsException();

		}

		@Override
		public boolean isCellEditable(int row, int col) {
			return false;
		}

		@Override
		public void setValueAt(Object value, int row, int col) {
			throw new IllegalStateException();
		}

	}

	private static final long serialVersionUID = -6344739502697068778L;

	private JButton btnFilter;

	final JButton clearButton;

	private JTable dataTable;

	JComboBox filterComboBox;
	private JTextField filterTextField;
	TableRowSorter<EntryTableModel> sorter;

	public EntryView() {

		dataTable = new JTable();
		JScrollPane tableScroll = new JScrollPane(dataTable);
		tableScroll
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		dataTable.setVisible(true);
		SpringLayout springLayout = new SpringLayout();
		springLayout.putConstraint(SpringLayout.NORTH, tableScroll, 0,
				SpringLayout.NORTH, this);
		springLayout.putConstraint(SpringLayout.WEST, tableScroll, 0,
				SpringLayout.WEST, this);
		springLayout.putConstraint(SpringLayout.EAST, tableScroll, 0,
				SpringLayout.EAST, this);
		setLayout(springLayout);
		add(tableScroll);

		JPanel panel = new JPanel();

		springLayout.putConstraint(SpringLayout.SOUTH, panel, 0,
				SpringLayout.SOUTH, this);
		springLayout.putConstraint(SpringLayout.WEST, panel, 0,
				SpringLayout.WEST, this);
		springLayout.putConstraint(SpringLayout.SOUTH, tableScroll, -5,
				SpringLayout.NORTH, panel);
		add(panel);
		panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

		JLabel filterLabel = new JLabel("Filter:");
		panel.add(filterLabel);

		filterComboBox = new JComboBox();
		panel.add(filterComboBox);

		filterTextField = new JTextField();
		filterTextField
				.setToolTipText("Apply a Regex filter to the table data. Press return to start filtering.");
		panel.add(filterTextField);
		filterTextField.setColumns(20);

		btnFilter = new JButton("Filter");
		btnFilter.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				setFilter(filterTextField.getText());

			}
		});

		panel.add(btnFilter);

		clearButton = new JButton("Clear");
		clearButton.setToolTipText("Clears the applied filter from the table");
		clearButton.setEnabled(false);
		panel.add(clearButton);
		filterTextField.addKeyListener(new KeyListener() {

			@Override
			public void keyPressed(KeyEvent e) {
				int key = e.getKeyCode();

				if (key == KeyEvent.VK_ENTER) {
					setFilter(filterTextField.getText());
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}
		});

		clearButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				setFilter(null);
			}
		});

	}

	public void display(IBattleStatistic battleStatistic) {
		List<Entry> entries = battleStatistic.getEntries();
		display(entries);
	}

	public void display(List<Entry> entries) {
		EntryTableModel model = new EntryTableModel(entries);
		String[] columnNames = model.getColumnNames();
		filterComboBox.removeAll();
		filterComboBox.addItem("All");
		for (int i = 0; i < columnNames.length; i++) {
			filterComboBox.addItem(columnNames[i]);
		}

		dataTable.setModel(model);
		sorter = new TableRowSorter<EntryTableModel>(model);
		dataTable.setRowSorter(sorter);
	}

	private void displayFilterApplied() {
		clearButton.setEnabled(true);
		btnFilter.setEnabled(false);
		filterComboBox.setEnabled(false);
	}

	private void displayFilterCleared() {
		clearButton.setEnabled(false);
		btnFilter.setEnabled(true);
		filterComboBox.setEnabled(true);
	}

	private void setFilter(String text) {
		if (text == null) {
			sorter.setRowFilter(null);
			displayFilterCleared();
			return;
		}

		RowFilter<EntryTableModel, Object> rf = null;
		// If current expression doesn't parse, don't update.
		try {
			int index = filterComboBox.getSelectedIndex() - 1;
			if (index == -1) {
				// All is selected
				rf = RowFilter.regexFilter(text, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
						10);
			} else {
				rf = RowFilter.regexFilter(text, index);
			}

		} catch (java.util.regex.PatternSyntaxException e) {
			return;
		}

		displayFilterApplied();
		sorter.setRowFilter(rf);
	}
}
